﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using SaiLing.Domain;
using SaiLing.Domain.Persistence.Relational;
using SaiLing.Domain.Specification;
using SaiLing.Repository;
using SaiLing.SingleSignOn.Application.Service.Interfaces;

namespace SaiLing.SingleSignOn.Application.Service.Providers
{
    public abstract class BaseService<T> : IBaseService<T> where T :  IEntity, new()
    {
        protected readonly IRepository<T> Repository;
        protected readonly IUnitOfWork UnitOfWork;

        protected BaseService(IUnitOfWork unitOfWork, IRepository<T> repository)
        {
            UnitOfWork = unitOfWork;
            Repository = repository;
        }

        #region IBaseServices<T> 成员

        public IPagedList<T> PageList<TS>(int pageIndex, int pageSize, ISpecification<T> specification, Expression<Func<T, TS>> orderByExpression, bool isDesc, bool? asNoTracking = true)
        {
            return Repository.PageList(pageIndex, pageSize, specification, orderByExpression, isDesc, asNoTracking);
        }

        public IQueryable<T> All<TS>(Expression<Func<T, TS>> orderByExpression, bool isDesc = true)
        {
            return Repository.All(orderByExpression);
        }

        public virtual IEnumerable<T> GetAll(bool? asNoTracking = true)
        {
            return Repository.GetAll(asNoTracking);
        }

        public IEnumerable<T> GetMany(ISpecification<T> specification, bool? asNoTracking = true)
        {
            return Repository.GetMany(specification, asNoTracking);
        }


        public IEnumerable<T> GetListByTopN<TS>(int topN, ISpecification<T> specification, Expression<Func<T, TS>> orderByExpression, bool isDesc, bool? asNoTracking = true)
        {
            return Repository.GetListByTopN(topN, specification, orderByExpression, isDesc, asNoTracking);
        }

        public virtual Task<T> GetByCondition(ISpecification<T> specification, bool? asNoTracking = false)
        {
            return Repository.GetByCondition(specification, asNoTracking);
        }

        public virtual Task<T> GetByKey(object key)
        {
            return Repository.GetByKey(key);
        }

        public virtual Task Add(T entity)
        {
           return Repository.Add(entity);
        }

        public virtual void Modify(T entity)
        {
            Repository.Modify(entity);
        }

        public void Update(T entity, params Expression<Func<T, object>>[] properties)
        {
            Repository.Update(entity, properties);
        }

        public virtual void Remove(T entity)
        {
            Repository.Remove(entity);
        }

        public virtual Task Remove(ISpecification<T> specification)
        {
           return Repository.Remove(specification);
        }

        public void LogicRemove(T entity)
        {
            Repository.LogicRemove(entity);
        }

        public Task LogicRemove(ISpecification<T> specification)
        {
           return Repository.LogicRemove(specification);
        }

        public virtual Task<bool> ExistsAsync(ISpecification<T> specification)
        {
            return Repository.ExistsAsync(specification);
        }


        public Task<int> SaveChangesAsync()
        {
           return UnitOfWork.SaveChangesAsync();
        }

        #endregion


        public int GetCount()
        {
            return Repository.GetCount();
        }

        public int GetCount(ISpecification<T> specification)
        {
            return Repository.GetCount(specification);
        }
       
    }
}
